@@ -99,9 +99,12 @@ $(document).ready -> |
||
99 | 99 |
$("#logs .spinner").stop(true, true).fadeOut -> |
100 | 100 |
$("#logs .refresh, #logs .clear").show() |
101 | 101 |
|
102 |
- $(".agent-show #show-tabs a[href='#logs']").on "click", fetchLogs |
|
103 |
- $("#logs .refresh").on "click", fetchLogs |
|
104 |
- $("#logs .clear").on "click", clearLogs |
|
102 |
+ $(".agent-show #show-tabs a[href='#logs'], #logs .refresh").on "click", fetchLogs |
|
103 |
+ $(".agent-show #logs .clear").on "click", clearLogs |
|
104 |
+ |
|
105 |
+ if tab = window.location.href.match(/tab=(\w+)\b/i)?[1] |
|
106 |
+ if tab in ["details", "logs"] |
|
107 |
+ $(".agent-show .nav-tabs li a[href='##{tab}']").click() |
|
105 | 108 |
|
106 | 109 |
# Editing Agents |
107 | 110 |
$("#agent_source_ids").on "change", showEventDescriptions |
@@ -82,6 +82,11 @@ img.spinner { |
||
82 | 82 |
overflow: hidden; |
83 | 83 |
} |
84 | 84 |
|
85 |
+span.not-applicable:after { |
|
86 |
+ color: #bbbbbb; |
|
87 |
+ content: "n/a"; |
|
88 |
+} |
|
89 |
+ |
|
85 | 90 |
// Navbar |
86 | 91 |
|
87 | 92 |
#job-indicator, #event-indicator { |
@@ -116,4 +121,4 @@ img.spinner { |
||
116 | 121 |
&.refresh { |
117 | 122 |
margin: 0 10px; |
118 | 123 |
} |
119 |
-} |
|
124 |
+} |
@@ -11,7 +11,7 @@ module ApplicationHelper |
||
11 | 11 |
if agent.working? |
12 | 12 |
'<span class="label label-success">Yes</span>'.html_safe |
13 | 13 |
else |
14 |
- '<span class="label label-warning">No</span>'.html_safe |
|
14 |
+ link_to '<span class="label label-warning">No</span>'.html_safe, agent_path(agent, :tab => (agent.recent_error_logs? ? 'logs' : 'details')) |
|
15 | 15 |
end |
16 | 16 |
end |
17 | 17 |
end |
@@ -88,7 +88,11 @@ class Agent < ActiveRecord::Base |
||
88 | 88 |
end |
89 | 89 |
|
90 | 90 |
def create_event(attrs) |
91 |
- events.create!({ :user => user }.merge(attrs)) |
|
91 |
+ if can_create_events? |
|
92 |
+ events.create!({ :user => user }.merge(attrs)) |
|
93 |
+ else |
|
94 |
+ error "This Agent cannot create events!" |
|
95 |
+ end |
|
92 | 96 |
end |
93 | 97 |
|
94 | 98 |
def validate_schedule |
@@ -117,7 +121,7 @@ class Agent < ActiveRecord::Base |
||
117 | 121 |
end |
118 | 122 |
|
119 | 123 |
def last_event_at |
120 |
- @memoized_last_event_at ||= events.select(:created_at).first.try(:created_at) |
|
124 |
+ @memoized_last_event_at ||= most_recent_event.try(:created_at) |
|
121 | 125 |
end |
122 | 126 |
|
123 | 127 |
def default_schedule |
@@ -140,6 +144,14 @@ class Agent < ActiveRecord::Base |
||
140 | 144 |
!cannot_receive_events? |
141 | 145 |
end |
142 | 146 |
|
147 |
+ def cannot_create_events? |
|
148 |
+ self.class.cannot_create_events? |
|
149 |
+ end |
|
150 |
+ |
|
151 |
+ def can_create_events? |
|
152 |
+ !cannot_create_events? |
|
153 |
+ end |
|
154 |
+ |
|
143 | 155 |
def set_last_checked_event_id |
144 | 156 |
if newest_event_id = Event.order("id desc").limit(1).pluck(:id).first |
145 | 157 |
self.last_checked_event_id = newest_event_id |
@@ -169,6 +181,14 @@ class Agent < ActiveRecord::Base |
||
169 | 181 |
@default_schedule |
170 | 182 |
end |
171 | 183 |
|
184 |
+ def cannot_create_events! |
|
185 |
+ @cannot_create_events = true |
|
186 |
+ end |
|
187 |
+ |
|
188 |
+ def cannot_create_events? |
|
189 |
+ !!@cannot_create_events |
|
190 |
+ end |
|
191 |
+ |
|
172 | 192 |
def cannot_receive_events! |
173 | 193 |
@cannot_receive_events = true |
174 | 194 |
end |
@@ -3,6 +3,8 @@ module Agents |
||
3 | 3 |
MAIN_KEYS = %w[title message text main value].map(&:to_sym) |
4 | 4 |
default_schedule "5am" |
5 | 5 |
|
6 |
+ cannot_create_events! |
|
7 |
+ |
|
6 | 8 |
description <<-MD |
7 | 9 |
The DigestEmailAgent collects any Events sent to it and sends them all via email when run. |
8 | 10 |
The email will be sent to your account's address and will have a `subject` and an optional `headline` before |
@@ -1,6 +1,7 @@ |
||
1 | 1 |
module Agents |
2 | 2 |
class PostAgent < Agent |
3 | 3 |
cannot_be_scheduled! |
4 |
+ cannot_create_events! |
|
4 | 5 |
|
5 | 6 |
description <<-MD |
6 | 7 |
Post Agent receives events from other agents and send those events as the contents of a post request to a specified url. `post_url` field must specify where you would like to receive post requests and do not forget to include URI scheme (`http` or `https`) |
@@ -4,6 +4,7 @@ require 'securerandom' |
||
4 | 4 |
module Agents |
5 | 5 |
class TwilioAgent < Agent |
6 | 6 |
cannot_be_scheduled! |
7 |
+ cannot_create_events! |
|
7 | 8 |
|
8 | 9 |
description <<-MD |
9 | 10 |
The TwilioAgent receives and collects events and sends them via text message or gives you a call when scheduled. |
@@ -47,8 +47,9 @@ |
||
47 | 47 |
<div class="control-group"> |
48 | 48 |
<%= f.label :sources, :class => 'control-label' %> |
49 | 49 |
<div class="controls link-region" data-can-receive-events="<%= @agent.can_receive_events? %>"> |
50 |
+ <% eventSources = (current_user.agents - [@agent]).find_all { |a| a.can_create_events? } %> |
|
50 | 51 |
<%= f.select(:source_ids, |
51 |
- options_for_select((current_user.agents - [@agent]).map {|s| [s.name, s.id] }, |
|
52 |
+ options_for_select(eventSources.map {|s| [s.name, s.id] }, |
|
52 | 53 |
@agent.source_ids), |
53 | 54 |
{}, { :multiple => true, :size => 5, :class => 'span4 select2' }) %> |
54 | 55 |
<span class='cannot-receive-events text-info'>This type of Agent cannot receive events.</span> |
@@ -8,53 +8,71 @@ |
||
8 | 8 |
<table class='table table-striped'> |
9 | 9 |
<tr> |
10 | 10 |
<th>Name</th> |
11 |
+ <th>Schedule</th> |
|
11 | 12 |
<th>Last Check</th> |
12 | 13 |
<th>Last Event Out</th> |
13 | 14 |
<th>Last Event In</th> |
14 |
- <th>Events</th> |
|
15 |
- <th>Schedule</th> |
|
15 |
+ <th>Events Created</th> |
|
16 | 16 |
<th>Working?</th> |
17 | 17 |
<th></th> |
18 | 18 |
</tr> |
19 | 19 |
|
20 | 20 |
<% @agents.each do |agent| %> |
21 |
- <tr> |
|
22 |
- <td> |
|
23 |
- <%= agent.name %> |
|
24 |
- <br/> |
|
25 |
- <span class='muted'><%= agent.short_type.titleize %></span> |
|
26 |
- </td> |
|
27 |
- <td> |
|
28 |
- <% if agent.cannot_be_scheduled? %> |
|
29 |
- N/A |
|
30 |
- <% else %> |
|
31 |
- <%= agent.last_check_at ? time_ago_in_words(agent.last_check_at) + " ago" : "never" %> |
|
32 |
- <% end %> |
|
33 |
- </td> |
|
34 |
- <td><%= agent.last_event_at ? time_ago_in_words(agent.last_event_at) + " ago" : "never" %></td> |
|
35 |
- <td> |
|
36 |
- <% if agent.cannot_receive_events? %> |
|
37 |
- N/A |
|
21 |
+ <tr> |
|
22 |
+ <td> |
|
23 |
+ <%= agent.name %> |
|
24 |
+ <br/> |
|
25 |
+ <span class='muted'><%= agent.short_type.titleize %></span> |
|
26 |
+ </td> |
|
27 |
+ <td> |
|
28 |
+ <% if agent.can_be_scheduled? %> |
|
29 |
+ <%= agent.schedule.to_s.humanize.titleize %> |
|
30 |
+ <% else %> |
|
31 |
+ <span class='not-applicable'></span> |
|
32 |
+ <% end %> |
|
33 |
+ </td> |
|
34 |
+ <td> |
|
35 |
+ <% if agent.can_be_scheduled? %> |
|
36 |
+ <%= agent.last_check_at ? time_ago_in_words(agent.last_check_at) + " ago" : "never" %> |
|
37 |
+ <% else %> |
|
38 |
+ <span class='not-applicable'></span> |
|
39 |
+ <% end %> |
|
40 |
+ </td> |
|
41 |
+ <td> |
|
42 |
+ <% if agent.can_create_events? %> |
|
43 |
+ <%= agent.last_event_at ? time_ago_in_words(agent.last_event_at) + " ago" : "never" %> |
|
44 |
+ <% else %> |
|
45 |
+ <span class='not-applicable'></span> |
|
46 |
+ <% end %> |
|
47 |
+ </td> |
|
48 |
+ <td> |
|
49 |
+ <% if agent.can_receive_events? %> |
|
50 |
+ <%= agent.last_receive_at ? time_ago_in_words(agent.last_receive_at) + " ago" : "never" %> |
|
51 |
+ <% else %> |
|
52 |
+ <span class='not-applicable'></span> |
|
53 |
+ <% end %> |
|
54 |
+ </td> |
|
55 |
+ <td> |
|
56 |
+ <% if agent.can_create_events? %> |
|
57 |
+ <%= link_to(agent.events_count || 0, events_path(:agent => agent.to_param)) %> |
|
58 |
+ <% else %> |
|
59 |
+ <span class='not-applicable'></span> |
|
60 |
+ <% end %> |
|
61 |
+ </td> |
|
62 |
+ <td><%= working(agent) %></td> |
|
63 |
+ <td> |
|
64 |
+ <div class="btn-group"> |
|
65 |
+ <%= link_to 'Show', agent_path(agent), class: "btn btn-mini" %> |
|
66 |
+ <%= link_to 'Edit', edit_agent_path(agent), class: "btn btn-mini" %> |
|
67 |
+ <%= link_to 'Delete', agent_path(agent), method: :delete, data: { confirm: 'Are you sure?' }, class: "btn btn-mini" %> |
|
68 |
+ <% if agent.can_be_scheduled? %> |
|
69 |
+ <%= link_to 'Run', run_agent_path(agent, :return => "index"), method: :post, class: "btn btn-mini" %> |
|
38 | 70 |
<% else %> |
39 |
- <%= agent.last_receive_at ? time_ago_in_words(agent.last_receive_at) + " ago" : "never" %> |
|
71 |
+ <%= link_to 'Run', "#", class: "btn btn-mini disabled" %> |
|
40 | 72 |
<% end %> |
41 |
- </td> |
|
42 |
- <td><%= link_to(agent.events_count || 0, events_path(:agent => agent.to_param)) %></td> |
|
43 |
- <td><%= (agent.schedule || "n/a").to_s.humanize.titleize %></td> |
|
44 |
- <td><%= working(agent) %></td> |
|
45 |
- <td> |
|
46 |
- <div class="btn-group"> |
|
47 |
- <%= link_to 'Show', agent_path(agent), class: "btn btn-mini" %> |
|
48 |
- <%= link_to 'Edit', edit_agent_path(agent), class: "btn btn-mini" %> |
|
49 |
- <%= link_to 'Delete', agent_path(agent), method: :delete, data: {confirm: 'Are you sure?'}, class: "btn btn-mini" %> |
|
50 |
- <% if agent.can_be_scheduled? %> |
|
51 |
- <%= link_to 'Run', run_agent_path(agent, :return => "index"), method: :post, class: "btn btn-mini" %> |
|
52 |
- <% else %> |
|
53 |
- <%= link_to 'Run', "#", class: "btn btn-mini disabled" %> |
|
54 |
- <% end %> |
|
55 |
- </div> |
|
56 |
- </td> |
|
57 |
- </tr> |
|
73 |
+ </div> |
|
74 |
+ </td> |
|
75 |
+ </tr> |
|
58 | 76 |
<% end %> |
59 | 77 |
</table> |
60 | 78 |
|
@@ -13,7 +13,7 @@ |
||
13 | 13 |
<% end %> |
14 | 14 |
<li><a href="#logs" data-toggle="tab" data-agent-id="<%= @agent.id %>"><i class='icon-list-alt'></i> Logs</a></li> |
15 | 15 |
|
16 |
- <% if @agent.events.count > 0 %> |
|
16 |
+ <% if @agent.can_create_events? && @agent.events.count > 0 %> |
|
17 | 17 |
<li><%= link_to '<i class="icon-random"></i> Events'.html_safe, events_path(:agent => @agent.to_param) %></li> |
18 | 18 |
<% end %> |
19 | 19 |
<li><%= link_to '<i class="icon-chevron-left"></i> Back'.html_safe, agents_path %></li> |
@@ -29,7 +29,7 @@ |
||
29 | 29 |
</li> |
30 | 30 |
<% end %> |
31 | 31 |
|
32 |
- <% if @agent.events.count > 0 %> |
|
32 |
+ <% if @agent.can_create_events? && @agent.events.count > 0 %> |
|
33 | 33 |
<li> |
34 | 34 |
<%= link_to '<i class="icon-trash"></i> Delete all events'.html_safe, remove_events_agent_path(@agent), method: :delete, data: {confirm: 'Are you sure you want to delete ALL events for this Agent?'}, :tabindex => "-1" %> |
35 | 35 |
</li> |
@@ -70,38 +70,60 @@ |
||
70 | 70 |
<%= @agent.short_type.titleize %> |
71 | 71 |
</p> |
72 | 72 |
|
73 |
- <p> |
|
74 |
- <b>Schedule:</b> |
|
75 |
- <%= (@agent.schedule || "n/a").humanize.titleize %> |
|
76 |
- </p> |
|
73 |
+ <% if @agent.can_be_scheduled? %> |
|
74 |
+ <p> |
|
75 |
+ <b>Schedule:</b> |
|
76 |
+ <%= (@agent.schedule || "n/a").humanize.titleize %> |
|
77 |
+ </p> |
|
77 | 78 |
|
78 |
- <p> |
|
79 |
- <b>Last checked:</b> |
|
80 |
- <% if @agent.cannot_be_scheduled? %> |
|
81 |
- N/A |
|
82 |
- <% else %> |
|
79 |
+ <p> |
|
80 |
+ <b>Last checked:</b> |
|
83 | 81 |
<%= @agent.last_check_at ? time_ago_in_words(@agent.last_check_at) + " ago" : "never" %> |
84 |
- <% end %> |
|
85 |
- </p> |
|
82 |
+ </p> |
|
83 |
+ <% end %> |
|
86 | 84 |
|
87 |
- <p> |
|
88 |
- <b>Last event created:</b> |
|
89 |
- <%= @agent.last_event_at ? time_ago_in_words(@agent.last_event_at) + " ago" : "never" %> |
|
90 |
- </p> |
|
85 |
+ <% if @agent.can_create_events? %> |
|
86 |
+ <p> |
|
87 |
+ <b>Last event created:</b> |
|
88 |
+ <%= @agent.last_event_at ? time_ago_in_words(@agent.last_event_at) + " ago" : "never" %> |
|
89 |
+ </p> |
|
90 |
+ <% end %> |
|
91 | 91 |
|
92 |
- <p> |
|
93 |
- <b>Last received event:</b> |
|
94 |
- <% if @agent.cannot_receive_events? %> |
|
95 |
- N/A |
|
96 |
- <% else %> |
|
92 |
+ <% if @agent.can_receive_events? %> |
|
93 |
+ <p> |
|
94 |
+ <b>Last received event:</b> |
|
97 | 95 |
<%= @agent.last_receive_at ? time_ago_in_words(@agent.last_receive_at) + " ago" : "never" %> |
98 |
- <% end %> |
|
99 |
- </p> |
|
96 |
+ </p> |
|
97 |
+ <% end %> |
|
100 | 98 |
|
101 |
- <p> |
|
102 |
- <b>Event count:</b> |
|
103 |
- <%= link_to @agent.events.count, events_path(:agent => @agent.to_param) %> |
|
104 |
- </p> |
|
99 |
+ <% if @agent.can_create_events? %> |
|
100 |
+ <p> |
|
101 |
+ <b>Events created:</b> |
|
102 |
+ <%= link_to @agent.events.count, events_path(:agent => @agent.to_param) %> |
|
103 |
+ </p> |
|
104 |
+ <% end %> |
|
105 |
+ |
|
106 |
+ <% if @agent.can_receive_events? %> |
|
107 |
+ <p> |
|
108 |
+ <b>Event sources:</b> |
|
109 |
+ <% if @agent.sources.length %> |
|
110 |
+ <%= @agent.sources.map { |source_agent| link_to(source_agent.name, agent_path(source_agent)) }.to_sentence.html_safe %> |
|
111 |
+ <% else %> |
|
112 |
+ None |
|
113 |
+ <% end %> |
|
114 |
+ </p> |
|
115 |
+ <% end %> |
|
116 |
+ |
|
117 |
+ <% if @agent.can_create_events? %> |
|
118 |
+ <p> |
|
119 |
+ <b>Event receivers:</b> |
|
120 |
+ <% if @agent.receivers.length %> |
|
121 |
+ <%= @agent.receivers.map { |receiver_agent| link_to(receiver_agent.name, agent_path(receiver_agent)) }.to_sentence.html_safe %> |
|
122 |
+ <% else %> |
|
123 |
+ None |
|
124 |
+ <% end %> |
|
125 |
+ </p> |
|
126 |
+ <% end %> |
|
105 | 127 |
|
106 | 128 |
<p> |
107 | 129 |
<b>Working:</b> |
@@ -43,6 +43,10 @@ |
||
43 | 43 |
</li> |
44 | 44 |
|
45 | 45 |
<li> |
46 |
+ <%= link_to 'About', 'https://github.com/cantino/huginn', :tabindex => "-1" %> |
|
47 |
+ </li> |
|
48 |
+ |
|
49 |
+ <li> |
|
46 | 50 |
<% if user_signed_in? %> |
47 | 51 |
<%= link_to 'Logout', destroy_user_session_path, :method => :delete, :tabindex => "-1" %> |
48 | 52 |
<% else %> |
@@ -114,13 +114,23 @@ describe Agent do |
||
114 | 114 |
end |
115 | 115 |
|
116 | 116 |
describe "#create_event" do |
117 |
+ before do |
|
118 |
+ @checker = Agents::SomethingSource.new(:name => "something") |
|
119 |
+ @checker.user = users(:bob) |
|
120 |
+ @checker.save! |
|
121 |
+ end |
|
122 |
+ |
|
117 | 123 |
it "should use the checker's user" do |
118 |
- checker = Agents::SomethingSource.new(:name => "something") |
|
119 |
- checker.user = users(:bob) |
|
120 |
- checker.save! |
|
124 |
+ @checker.check |
|
125 |
+ Event.last.user.should == @checker.user |
|
126 |
+ end |
|
121 | 127 |
|
122 |
- checker.check |
|
123 |
- Event.last.user.should == checker.user |
|
128 |
+ it "should log an error if the Agent has been marked with 'cannot_create_events!'" do |
|
129 |
+ mock(@checker).can_create_events? { false } |
|
130 |
+ lambda { |
|
131 |
+ @checker.check |
|
132 |
+ }.should_not change { Event.count } |
|
133 |
+ @checker.logs.first.message.should =~ /cannot create events/i |
|
124 | 134 |
end |
125 | 135 |
end |
126 | 136 |
|
@@ -52,8 +52,12 @@ |
||
52 | 52 |
display: block; |
53 | 53 |
float: right; |
54 | 54 |
text-decoration: none; |
55 |
- padding-left: 5px; |
|
55 |
+ padding: 0 5px; |
|
56 | 56 |
border: 0 !important; |
57 | 57 |
color: blue; |
58 |
+ |
|
59 |
+ &:hover { |
|
60 |
+ background-color: #bbb; |
|
61 |
+ } |
|
58 | 62 |
} |
59 | 63 |
} |